package com.jsits.v2x.bx05.server;

import com.jsits.v2x.bx05.config.Bx05Config;
import com.jsits.v2x.bx05.dto.ProgramDto;
import com.jsits.v2x.common.dto.ControlDto;
import com.jsits.v2x.common.enums.DevicePosition;
import com.jsits.v2x.common.enums.TextContent;
import lombok.extern.slf4j.Slf4j;
import onbon.bx05.Bx5GEnv;
import onbon.bx05.Bx5GScreen.Result;
import onbon.bx05.Bx5GScreenClient;
import onbon.bx05.area.TextCaptionBxArea;
import onbon.bx05.area.page.TextBxPage;
import onbon.bx05.file.ProgramBxFile;
import onbon.bx05.message.global.ACK;
import onbon.bx05.utils.TextBinary.Alignment;
import org.springframework.beans.factory.annotation.Autowired;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Bx05型号卡操作工具类
 * 锁定的节目会在屏幕上轮换播放
 * @author zhy
 */
@Slf4j
public class Bx05ControlServer {
    public static Bx05Config bx05Config;

    /**
     * 屏幕锁定节目缓存表<屏幕位置,节目号>
     */
    private static Map<DevicePosition, Integer> lockProgramMap = new HashMap<DevicePosition, Integer>();

    /**
     * 节目对应节目号缓存表<节目内容,节目号>
     */
    private static Map<TextContent, Integer> programMap = new HashMap<TextContent, Integer>();

    /**
     * 连接map<屏幕位置,连接>
     */
    private static Map<DevicePosition, Bx5GScreenClient> connectMap = new HashMap<DevicePosition, Bx5GScreenClient>();


    /**
     * 连接次数
     */
    private static Integer connTime = 0;

    /**
     * 锁定节目
     */
    public static void lockProgram(Bx5GScreenClient screen, DevicePosition devicePosition, Integer programId) {
        try {
            // 上锁
            Result<ACK> result = screen.lockProgram(programId, 1);
            System.out.println(result);
            // 加入缓存
            lockProgramMap.put(devicePosition, programId);
            log.info("lock info : " + devicePosition + "-" + programId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据ip获取连接对象
     *
     * @param devicePosition
     * @return
     */
    private static void unlockAndLock(Bx5GScreenClient screen, DevicePosition devicePosition, Integer lockedProgram, Integer programId) {
        try {
            // 解锁
            if (lockedProgram != null) {
                Result<ACK> uresult = screen.unlockProgram(lockedProgram);
                log.info("unlock program {} : {}", lockedProgram, uresult.toString());
            }
            // 加锁
            Result<ACK> lresult = screen.lockProgram(programId, 1);
            log.info("unlock program {} : {}", lockedProgram, lresult.toString());
            // 更新缓存
            lockProgramMap.put(devicePosition, programId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化解锁所有节目
     *
     * @param devicePosition
     * @return
     */
    private static void unlockAllProgram(DevicePosition devicePosition) {
        try {
            // 先获取连接
            Bx5GScreenClient screen = getBx05Connection(devicePosition);
            for (int i = 0; i < 1; i = 0) {
                // 如果连接成功或者连接次数达到上限
                if (screen != null || connTime >= 20) {
                    connTime = 0;
                    break;
                } else {
                    connTime++;
                    screen = getBx05Connection(devicePosition);
                }
            }

            for (int i = 0; i < 8; i++) {
                screen.unlockProgram(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化
     */
    public static void init() {
        //节目号配置信息存放到map
        programMap.put(TextContent.TEXT_CONTENT_MAIN_UNDER_NOMAN, bx05Config.getMainUnderNomanID());
        programMap.put(TextContent.TEXT_CONTENT_MAIN_UNDER_MAN, bx05Config.getMainUnderManID());
        programMap.put(TextContent.TEXT_CONTENT_MAIN_OVER_NOMAN, bx05Config.getMainOverNomanID());
        programMap.put(TextContent.TEXT_CONTENT_MAIN_OVER_MAN, bx05Config.getMainOverManID());
        programMap.put(TextContent.TEXT_CONTENT_SUB_SIDES, bx05Config.getSubSidesID());
        programMap.put(TextContent.TEXT_CONTENT_SUB_LEFT, bx05Config.getSubLeftID());
        programMap.put(TextContent.TEXT_CONTENT_SUB_RIGHT, bx05Config.getSubRightID());
        programMap.put(TextContent.TEXT_CONTENT_SUB_NONE, bx05Config.getSubNoneID());

        // Bx05初始化
        try {
            Bx5GEnv.initial("log.properties");
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        //清空每个屏幕上的内容
        if(bx05Config.getHasMain1() > 0) {
            unlockAllProgram(DevicePosition.DEVICE_POSITION_MAIN_1);
        }
        if(bx05Config.getHasMain2() > 0) {
            unlockAllProgram(DevicePosition.DEVICE_POSITION_MAIN_2);
        }
        if(bx05Config.getHasSub1() > 0) {
            unlockAllProgram(DevicePosition.DEVICE_POSITION_SUB_1);
        }
        if(bx05Config.getHasSub2() > 0) {
            unlockAllProgram(DevicePosition.DEVICE_POSITION_SUB_2);
        }
    }

    /**
     * bx05系列卡发送节目方法
     * @param controlDto
     */
    public static void sendCtrontrolData(ControlDto controlDto) {
        // 首先判断该位置是否有屏幕需要控制
        if((controlDto.getDevicePosition().equals(DevicePosition.DEVICE_POSITION_MAIN_1) && bx05Config.getHasMain1() > 0)
        || (controlDto.getDevicePosition().equals(DevicePosition.DEVICE_POSITION_MAIN_2) && bx05Config.getHasMain2() > 0)
        || (controlDto.getDevicePosition().equals(DevicePosition.DEVICE_POSITION_SUB_1) && bx05Config.getHasSub1() > 0)
        || (controlDto.getDevicePosition().equals(DevicePosition.DEVICE_POSITION_SUB_2) && bx05Config.getHasSub2() > 0)) {

            DevicePosition devicePosition = controlDto.getDevicePosition();
            Bx5GScreenClient screen = getBx05Connection(devicePosition);

            if (screen != null) {
                // 如果已经存在锁定节目信息
                Integer lockedProgram = lockProgramMap.get(devicePosition);
                Integer programId = programMap.get(controlDto.getTextContent());
                if(lockedProgram == programId){
                    log.debug("positon" + devicePosition + " is same with  last " + lockedProgram);
                    return;
                }
                if (lockedProgram != null) {
                    unlockAndLock(screen, devicePosition, lockedProgram, programId);
                } else {
                    // 锁定节目
                    lockProgram(screen, devicePosition, programId);
                }
            }
        }
    }

    /**
     * 获取屏幕连接方法
     *
     * @param devicePosition
     * @return
     */
    private static Bx5GScreenClient getBx05Connection(DevicePosition devicePosition) {
        // 先从缓存map中获取
        Bx5GScreenClient screen = connectMap.get(devicePosition);
        // 如果没获取到或者链接的isConnect属性为false
        if (screen == null || !screen.isConnected()) {
            String ip = "";
            switch (devicePosition) {
                case DEVICE_POSITION_MAIN_1:
                    ip = bx05Config.getMain1Ip();
                    break;
                case DEVICE_POSITION_MAIN_2:
                    ip = bx05Config.getMain2Ip();
                    break;
                case DEVICE_POSITION_SUB_1:
                    ip = bx05Config.getSub1Ip();
                    break;
                case DEVICE_POSITION_SUB_2:
                    ip = bx05Config.getSub2Ip();
                    break;
                default:
                    break;
            }
            // 就进行重新连接
            Bx5GScreenClient newScreen = new Bx5GScreenClient("MyScreen");
            if (newScreen.connect(ip, bx05Config.getServerPort())) {
                // 放入结果集
                screen = newScreen;
                // 并更新缓存
                connectMap.put(devicePosition, newScreen);
            }
        }
        // 返回结果
        return screen;
    }

    /**
     * 向屏幕写入预设节目
     */
    public static void writePrograms() {
        //各位置屏幕的参数
        List<ProgramDto> programDtoList = new ArrayList<>();
        if(bx05Config.getHasMain1() > 0) {
            ProgramDto main1ProgramDto = new ProgramDto();
            main1ProgramDto.setDevicePosition(DevicePosition.DEVICE_POSITION_MAIN_1);
            main1ProgramDto.setIp(bx05Config.getMain1Ip());
            main1ProgramDto.setWidth(bx05Config.getMain1Width());
            main1ProgramDto.setHeight(bx05Config.getMain1Height());
            main1ProgramDto.setFontSize(bx05Config.getMain1FontSize());
            programDtoList.add(main1ProgramDto);
        }
        if(bx05Config.getHasMain2() > 0) {
            ProgramDto main2ProgramDto = new ProgramDto();
            main2ProgramDto.setDevicePosition(DevicePosition.DEVICE_POSITION_MAIN_2);
            main2ProgramDto.setIp(bx05Config.getMain2Ip());
            main2ProgramDto.setWidth(bx05Config.getMain2Width());
            main2ProgramDto.setHeight(bx05Config.getMain2Height());
            main2ProgramDto.setFontSize(bx05Config.getMain2FontSize());
            programDtoList.add(main2ProgramDto);
        }
        if(bx05Config.getHasSub1() > 0) {
            ProgramDto sub1ProgramDto = new ProgramDto();
            sub1ProgramDto.setDevicePosition(DevicePosition.DEVICE_POSITION_SUB_1);
            sub1ProgramDto.setIp(bx05Config.getSub1Ip());
            sub1ProgramDto.setWidth(bx05Config.getSub1Width());
            sub1ProgramDto.setHeight(bx05Config.getSub1Height());
            sub1ProgramDto.setFontSize(bx05Config.getSub1FontSize());
            programDtoList.add(sub1ProgramDto);
        }
        if(bx05Config.getHasSub2() > 0) {
            ProgramDto sub2ProgramDto = new ProgramDto();
            sub2ProgramDto.setDevicePosition(DevicePosition.DEVICE_POSITION_SUB_2);
            sub2ProgramDto.setIp(bx05Config.getSub2Ip());
            sub2ProgramDto.setWidth(bx05Config.getSub2Width());
            sub2ProgramDto.setHeight(bx05Config.getSub2Height());
            sub2ProgramDto.setFontSize(bx05Config.getSub2FontSize());
            programDtoList.add(sub2ProgramDto);
        }
        //屏幕显示的内容
        Map<Integer, String> bxFiles = new HashMap<>();
        bxFiles.put(bx05Config.getMainUnderNomanID(), bx05Config.getMainUnderNoman());
        bxFiles.put(bx05Config.getMainUnderManID(), bx05Config.getMainUnderMan());
        bxFiles.put(bx05Config.getMainOverNomanID(), bx05Config.getMainOverNoman());
        bxFiles.put(bx05Config.getMainOverManID(), bx05Config.getMainOverMan());
        //bxFiles.put(bx05Config.getSubSidesID(), bx05Config.getSubSides());
        //bxFiles.put(bx05Config.getSubLeftID(), bx05Config.getSubLeft());
        //bxFiles.put(bx05Config.getSubRightID(), bx05Config.getSubRight());
        //bxFiles.put(bx05Config.getSubNoneID(), bx05Config.getSubNone());
        //向每个屏幕分别写入
        for(ProgramDto programDto : programDtoList) {
            Bx5GScreenClient screenClient = getBx05Connection(programDto.getDevicePosition());
            List<ProgramBxFile> programBxFileList = new ArrayList();
            //主路节目
            for(Map.Entry<Integer, String> entryMainBxFile : bxFiles.entrySet()) {
                ProgramBxFile program = new ProgramBxFile(String.format("P%03d", entryMainBxFile.getKey()),  screenClient.getProfile());
                program.setFrameShow(false);
                TextCaptionBxArea area = new TextCaptionBxArea(0, 0, programDto.getWidth(), programDto.getHeight(), screenClient.getProfile());
                TextBxPage page1 = new TextBxPage(entryMainBxFile.getValue());
                System.out.println(page1.getText());
                page1.setBackground(Color.BLACK);
                page1.setHorizontalAlignment(Alignment.CENTER);
                page1.setVerticalAlignment(Alignment.CENTER);
                page1.setFont(new Font("宋体", 0, programDto.getFontSize()));
                page1.setForeground(Color.RED);
                area.addPage(page1);
                program.addArea(area);
                programBxFileList.add(program);
            }

            //向屏幕写入节目内容
            try {
                screenClient.deletePrograms();
                screenClient.writePrograms(programBxFileList);
                System.out.print("success");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.print("failed");
            }
        }
    }
}
